#pragma once
#include <iostream>
#include <unistd.h>
#include <time.h>
#include <string>
#include <sstream>
#include <fstream>
#include <filesystem>
#include <functional>
// [2025-08-04 15:03:20] [INFO] [206234] [文件名] [行号] 信息

namespace fs = std::filesystem;

namespace LogMoudle
{
    // // 抽象类 回调执行方法即多态
    // class LogVirtual
    // {
    // public:
    //     virtual ~LogVirtual() = default;
    //     virtual void Refreshpolicy() = 0;
    // };

    // 获取当前时间 2025-08-04 15:03:20
    std::string GetCurrentTime()
    {
        time_t cur_time = time(nullptr);
        struct tm *p = localtime(&cur_time);

        char buffer[1024];
        int n = snprintf(buffer, sizeof(buffer) - 1, "%4d-%02d-%02d %02d:%02d:%02d", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
        buffer[n] = 0;

        return buffer;
    }

    enum LogLevel
    {
        DEBUG,
        INFOMATION, // 普通信息
        WARNING,
        ERROR, // 错误
        FATAL, // 致命的
    };

    std::string GetLevel(enum LogLevel le)
    {
        switch (le)
        {
        case DEBUG:
            return "DEBUG";
            break;
        case INFOMATION:
            return "INFOMATION";
            break;
        case WARNING:
            return "WARNING";
            break;
        case ERROR:
            return "ERROR";
            break;
        case FATAL:
            return "FATAL";
            break;
        default:
            "NONE";
            break;
        }

        return "NONE";
    }

    void PrintFile(std::string info)
    {
        // // 定义文件路径
        fs::path file_path = "LOG.txt";

        // // 检查文件是否存在
        // if (!fs::exists(file_path))
        // {

        // }

        std::ofstream file(file_path,std::ios_base::app);
        file << info << std::endl;
        file.close();
    }

    void PrintConsole(std::string info)
    {
        std::cout << info << std::endl;
    }

    using print_t = std::function<void(std::string info)>;
    class Message
    {
    public:
        Message(std::string level, std::string name, std::string line, print_t *ptrLog)
            : _level(level), _name(name), _line(line), _ptrLog(ptrLog)
        {
            _curtime = GetCurrentTime();
            _pid = std::to_string(getpid());

            // 析构时打印文字
            char buffer[1024];
            int n = snprintf(buffer, sizeof(buffer) - 1, "[%s] [%s] [%s] [%s] [%s]:",
                             _curtime.c_str(),
                             _level.c_str(), _pid.c_str(), _name.c_str(), _line.c_str());
            buffer[n] = 0;
            _ostream << buffer;
        }

        ~Message()
        {
            //std::cout<<"开始打印了:"<<_ostream.str()<<std::endl;
            _ptrLog->operator()(_ostream.str());
        }

        template <class T>
        Message &operator<<(T info)
        {
            _ostream << info;
            return *this;
        }

        // [2025-08-04 15:03:20] [INFO] [206234] [文件名] [行号] 信息
    private:
        std::string _pid;
        std::string _curtime;
        std::string _level;
        std::string _name;
        std::string _line;
        std::ostringstream _ostream;
        print_t *_ptrLog;
    };
    class Log
    {
    public:
        Log()
        {
            _print = PrintConsole;
        }
        ~Log() {}

        void FileRefresh()
        {
            _print = PrintFile;
        }
        void ConsoleRefresh()
        {
            _print = PrintConsole;
        }

        void PrintInfo(std::string info)
        {
            _print(info);
        }

        Message SendInfo(std::string level, std::string name, std::string line)
        {
            
            return Message (level, name, line, &_print);
        }

    private:
        print_t _print; // 打印策略
    };
}

LogMoudle::Log logger;
#define LOG(level) logger.SendInfo(GetLevel(level), __FILE__, std::to_string(__LINE__))
#define LOG_CONSOLE()  logger.ConsoleRefresh()
#define LOG_FILE()  logger.FileRefresh()
